package com.link_with_health.webSocket;

import com.alibaba.fastjson.JSONObject;
import com.link_with_health.config.ApplicationContextAwareGetBean;
import com.link_with_health.model.TalkRoomEntity;
import com.link_with_health.service.TalkRoomService;
import com.link_with_health.utils.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Enumeration;

@ServerEndpoint("/online-chat/{inquiryId}/{userId}")
@Component
@Scope("prototype")
public class TalkRoomServer {

    @Resource(name = "talkRoomService")
    private TalkRoomService service;

    private final Logger logger = LoggerFactory.getLogger(TalkRoomServer.class);

    /**
     * concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
     */

    private static ConcurrentHashMap<String, ConcurrentHashMap<String,Session>>
            allTalkRoomPool = new ConcurrentHashMap<>();

    /**
     * 根据inquiry id 保存聊天信息
     */
    private static ConcurrentHashMap<String, StringBuffer> historyMsg = new ConcurrentHashMap<>();
    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;
    /**
     * 接收userId
     */
    private String userId = "";
    /**
     * 接受的userId
     */
    private String inquiryId = "";


    @OnOpen
    public void onOpen(Session session
            , @PathParam("inquiryId") String inquiryId
            ,@PathParam("userId") String userId) {
        this.session = session;
        this.userId = userId;
        this.inquiryId = inquiryId;
        if(service == null)
            service = ApplicationContextAwareGetBean
                    .getBean(TalkRoomService.class);

        //初始化webSocket
        initWebSocket();


    }

    /**
     *
     * @param message 传输的信息
     * @param session webSocket的会话
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            this.sendMessage(message);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("连接异常...");
        error.printStackTrace();
    }

    @OnClose
    public void onClose() {
        String msg = "会诊编号+ "+this.inquiryId+"用户id "+this.userId;
        System.out.println("连接关闭=> "+msg);

        ConcurrentHashMap<String,Session> map = allTalkRoomPool.get(inquiryId);
        try{
            //移除会话
            map.remove(userId);
            logger.info("userId: "+ userId +" leave");
            }catch(Exception e){
                logger.error(" error=>",e);
        }
        //如果当前会话组没人 移除会话组
        if(map.isEmpty()) {
            allTalkRoomPool.remove(inquiryId);
            logger.info("[close to TalkRoomServer for "
                    + "inquiryId: "+ inquiryId + " ]");
        }
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        if (message.equals("心跳")) {
            this.session.getBasicRemote().sendText(message);
        }
        ConcurrentHashMap<String,Session> map = allTalkRoomPool.get(inquiryId);
        Enumeration<String> keys = map.keys();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement();
            if (map.get(key) == null) {
                map.remove(key);
                System.err.println(key + " : null");
                continue;
            }
            Session sessionValue = map.get(key);
            if (sessionValue.isOpen()) {
                System.out.println("发消息给: " + key + " ,message: " + message);
                sessionValue.getBasicRemote().sendText(message);
            } else {
                System.err.println(key + ": not open");
                sessionValue.close();
                map.remove(key);
            }
        }
    }

    /**
     * message 由前端的json对象通过JSON.stringify()方法
     * 转成字符串获得
     * 其结构为
     * {
     *       "inquiryId": "" //会诊信息
     *      "receiver" : "" //接受者
     *      "sender" : "" //发送者
     *      "content" : "" //文本内容
     *      "sendTime" : ""//发送时间
     * }
     * @param message 传输的消息
     * @throws IOException 异常
     */
    public void sendOneToOne(String message) throws IOException{
        JSONObject jsonStr = new JSONObject();
        try {
            jsonStr = JsonUtil.str2JsonObject(message);
        } catch (Exception e) {
            logger.error("[error in talkRoom sendOneToOne]",e);
        }
        String sender = jsonStr.getString("sender");
        String receiver = jsonStr.getString("receiver");

        String inquiryId = jsonStr.getString("inquiryId");

        Session receiverSession = allTalkRoomPool.get(inquiryId).get(receiver);

        String content = jsonStr.getString("content");
        receiverSession.getBasicRemote().sendText(content);

        System.out.println(sender + " send message to "
                + receiver+"\ncontent: "+ content);

        TalkRoomEntity entity = new TalkRoomEntity();
        entity.setInquiryId(Long.parseLong(inquiryId));
        entity.setMessage(message);
        try {
            service.addTalkRoom(entity);
        } catch (Exception e) {
            logger.error("[record message failed]",e);
        }

    }

    /**
     * 发送自定义消息
     */
    public static void sendInfo(String message
            , @PathParam("inquiryId")String inquiryId
            , @PathParam("userId") String userId) throws IOException {
        System.out.println("发送消息到:" + userId + "，内容:" + message);
        ConcurrentHashMap<String,Session> webSocketMap
                = allTalkRoomPool.get(inquiryId);
        if(webSocketMap == null){
            throw new IOException("[failed to get ]");
        }

        if ("".equals(userId) && webSocketMap.containsKey(userId)) {
            webSocketMap.get(userId).getBasicRemote().sendText(message);
            //webSocketServer.sendMessage(message);
        } else {
            System.out.println("用户" + userId + ",不在线！");
        }
    }


    public synchronized void initWebSocket() {
        ConcurrentHashMap<String,Session> webSocketMap;
        if(!allTalkRoomPool.containsKey(this.inquiryId)){
            webSocketMap = new ConcurrentHashMap<>();
        } else
            webSocketMap = allTalkRoomPool.get(inquiryId);
        /**
         * 连接被打开：向socket-map中添加session
         */
        webSocketMap.put(userId, session);
        allTalkRoomPool.put(inquiryId,webSocketMap);
        System.out.println(userId + " - 连接建立成功...");
        System.out.println(inquiryId + "-会诊编号");
    }




}
